package com.zc.manager.device.service.impl;

import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.zc.manager.device.domain.IotProtocol;
import com.zc.manager.device.mapper.IotProtocolMapper;
import com.zc.manager.device.service.IIotProtocolService;
import com.zc.supports.protocol.management.ProtocolSupportLoader;
import com.zc.supports.protocol.management.ProtocolSupportManager;
import com.zc.web.exception.BusinessException;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.List;

/**
 * 协议Service业务层处理
 *
 * @author xiepufeng
 * @date 2022-08-30
 */
@Service
public class IotProtocolServiceImpl implements IIotProtocolService
{
    @Resource
    private IotProtocolMapper iotProtocolMapper;

    @Resource
    private ProtocolSupportLoader loader;

    @Resource
    private ProtocolSupportManager supportManager;

    /**
     * 查询协议
     *
     * @param id 协议主键
     * @return 协议
     */
    @Override
    public IotProtocol selectIotProtocolById(String id)
    {
        return iotProtocolMapper.selectIotProtocolById(id);
    }

    /**
     * 查询协议列表
     *
     * @param iotProtocol 协议
     * @return 协议
     */
    @Override
    public List<IotProtocol> selectIotProtocolList(IotProtocol iotProtocol)
    {
        return iotProtocolMapper.selectIotProtocolList(iotProtocol);
    }

    /**
     * 新增协议
     *
     * @param iotProtocol 协议
     * @return 结果
     */
    @Override
    public int insertIotProtocol(IotProtocol iotProtocol)
    {

        // 协议ID
        String id = iotProtocol.getId();

        // 校验协议ID是否重复
        // 根据协议ID查询协议信息
        IotProtocol iotProtocol1 = iotProtocolMapper.selectIotProtocolById(id);

        // 存在
        if (iotProtocol1 != null) {
            // 存在则报错异常
            throw new ServiceException("协议ID不能重复！", HttpStatus.CONFLICT);
        }

        iotProtocol.setCreateTime(DateUtils.getNowDate());
        return iotProtocolMapper.insertIotProtocol(iotProtocol);
    }

    /**
     * 修改协议
     *
     * @param iotProtocol 协议
     * @return 结果
     */
    @Override
    public int updateIotProtocol(IotProtocol iotProtocol)
    {

        // 协议ID
        String id = iotProtocol.getId();

        // 校验协议ID是否重复
        // 根据协议ID查询协议信息
        IotProtocol protocol = iotProtocolMapper.selectIotProtocolById(id);

        if (protocol == null) {
            // 存在则报错异常
            throw new ServiceException("协议ID不存在！", HttpStatus.CONFLICT);
        }

        // 发布状态
        Integer publishState = protocol.getPublishState();

        // 不允许修改已发布的协议
        if(publishState.equals(IotProtocol.DEPLOYED)) {
            throw new ServiceException("协议已发布，不允许修改！", HttpStatus.NOT_FOUND);
        }


        iotProtocol.setUpdateTime(DateUtils.getNowDate());
        return iotProtocolMapper.updateIotProtocol(iotProtocol);
    }

    /**
     * 批量删除协议
     *
     * @param ids 需要删除的协议主键
     * @return 结果
     */
    @Override
    public int deleteIotProtocolByIds(String[] ids)
    {

        for (String id : ids) {
            IotProtocol iotProtocol = selectIotProtocolById(id);

            if (iotProtocol != null && iotProtocol.getPublishState().equals(IotProtocol.DEPLOYED)) {
                throw new ServiceException(iotProtocol.getProtocolName() + ":协议已发布，不能删除！");
            }
        }

        return iotProtocolMapper.deleteIotProtocolByIds(ids);
    }

    /**
     * 删除协议信息
     *
     * @param id 协议主键
     * @return 结果
     */
    @Override
    public int deleteIotProtocolById(String id)
    {

        IotProtocol iotProtocol = selectIotProtocolById(id);

        if (iotProtocol != null && iotProtocol.getPublishState().equals(IotProtocol.DEPLOYED)) {
            throw new ServiceException(iotProtocol.getProtocolName() + ":协议已发布，不能删除！");
        }

        return iotProtocolMapper.deleteIotProtocolById(id);
    }

    /**
     * 部署协议
     *
     * @param id 协议主键
     * @return
     */
    @Override
    public int deployProtocol(String id) {

        // 根据id获取协议信息
        IotProtocol protocol = iotProtocolMapper.selectIotProtocolById(id);

        if (protocol == null) {
            throw new ServiceException("无法获取当前协议信息", HttpStatus.NOT_FOUND);
        }

        // 加载协议
        Mono.just(protocol)
                 .map(IotProtocol::toDeployDefinition)
                 .flatMap(def->loader.load(def).thenReturn(def))
                 .onErrorMap(err -> new BusinessException("无法加载协议:" + err.getMessage(), err))
                 .flatMap(supportManager::save)
                 .block();


        // 设置状态为已发布
        protocol.setPublishState(IotProtocol.DEPLOYED);
        return iotProtocolMapper.updateIotProtocol(protocol);
    }

    /**
     * 卸载协议
     *
     * @param id 协议主键
     * @return
     */
    @Override
    public int undeployProtocol(String id) {
        // 根据id获取协议信息
        IotProtocol protocol = iotProtocolMapper.selectIotProtocolById(id);

        if (protocol == null) {
            throw new ServiceException("无法获取当前协议信息", HttpStatus.NOT_FOUND);
        }

        Mono.just(protocol)
                .map(IotProtocol::toUnDeployDefinition)
                .flatMap(supportManager::save)
                .block();

        // 设置状态为未发布
        protocol.setPublishState(IotProtocol.UNDEPLOY);
        return iotProtocolMapper.updateIotProtocol(protocol);
    }
}
